<!DOCTYPE html>
<html>

<head>
  <title>Quarkus - Generating JAX-RS resources with Panache</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/rest-data-panache" />
  <meta property="og:title" content="Quarkus - Generating JAX-RS resources with Panache" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/rest-data-panache">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Quarkus - Generating JAX-RS resources with Panache</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#setting-up-rest-data-with-panache">Setting up REST Data with Panache</a></li>
<li><a href="#generating-resources">Generating resources</a>
<ul class="sectlevel2">
<li><a href="#panacheentityresource">PanacheEntityResource</a></li>
<li><a href="#panacherepositoryresource">PanacheRepositoryResource</a></li>
<li><a href="#the-generated-resource">The generated resource</a></li>
</ul>
</li>
<li><a href="#resource-customisation">Resource customisation</a>
<ul class="sectlevel2">
<li><a href="#available-options">Available options</a></li>
</ul>
</li>
<li><a href="#response-body-examples">Response body examples</a>
<ul class="sectlevel2">
<li><a href="#get-people1">GET /people/1</a></li>
<li><a href="#get-peoplepage0size2">GET /people?page=0&amp;size=2</a></li>
</ul>
</li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>A lot of web applications are monotonous CRUD applications with REST APIs that are tedious to write.
To streamline this task, REST Data with Panache extension can generate the basic CRUD endpoints for your entities and repositories.</p>
</div>
<div class="paragraph">
<p>While this extension is still experimental and provides a limited feature set, we hope to get an early feedback for it.
Currently this extension supports Hibernate ORM with Panache and can generate CRUD resources that work with <code>application/json</code> and <code>application/hal+json</code> content.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>This technology is considered experimental.</p>
</div>
<div class="paragraph">
<p>In <em>experimental</em> mode, early feedback is requested to mature the idea.
There is no guarantee of stability nor long term presence in the platform until the solution matures.
Feedback is welcome on our <a href="https://groups.google.com/d/forum/quarkus-dev">mailing list</a> or as issues in our <a href="https://github.com/quarkusio/quarkus/issues">GitHub issue tracker</a>.</p>
</div>
<div class="paragraph">
<p>For a full list of possible extension statuses, check our <a href="https://quarkus.io/faq/#extension-status">FAQ entry</a>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="setting-up-rest-data-with-panache"><a class="anchor" href="#setting-up-rest-data-with-panache"></a>Setting up REST Data with Panache</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To begin with:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Add the required dependencies to your <code>pom.xml</code></p>
<div class="ulist">
<ul>
<li>
<p>Hibernate ORM REST Data with Panache extension (<code>quarkus-hibernate-orm-rest-data-panache</code>)</p>
</li>
<li>
<p>A JDBC driver extension (<code>quarkus-jdbc-postgresql</code>, <code>quarkus-jdbc-h2</code>, <code>quarkus-jdbc-mariadb</code>, &#8230;&#8203;)</p>
</li>
<li>
<p>One of the RESTEasy JSON serialization extensions (<code>quarkus-resteasy-jackson</code> or <code>quarkus-resteasy-jsonb</code>)</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
        &lt;artifactId&gt;quarkus-hibernate-orm-rest-data-panache&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
        &lt;artifactId&gt;quarkus-jdbc-postgresql&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
        &lt;artifactId&gt;quarkus-resteasy-jackson&lt;/artifactId&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Implement the Panache entities and/or repositories as explained in the <a href="hibernate-orm-panache">Hibernate ORM with Panache guide</a>.</p>
</li>
<li>
<p>Define the interfaces for generation as explained in the sections below.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="generating-resources"><a class="anchor" href="#generating-resources"></a>Generating resources</h2>
<div class="sectionbody">
<div class="paragraph">
<p>REST Data with Panache generates JAX-RS resources based on the interfaces available in your application.
For each entity and repository that you want to generate, provide an interface that extends either <code>PanacheEntityResource</code> or <code>PanacheRepositoryResource</code> interface.
<em>Do not implement these interfaces and don&#8217;t provide custom methods because they will be ignored.</em> You can, however, override the methods from the extended interface in order to customize them (see the section at the end).</p>
</div>
<div class="sect2">
<h3 id="panacheentityresource"><a class="anchor" href="#panacheentityresource"></a>PanacheEntityResource</h3>
<div class="paragraph">
<p>If your application has an entity (e.g. <code>Person</code>) that extends either <code>PanacheEntity</code> or <code>PanacheEntityBase</code> class, you could instruct REST Data with Panache to generate its JAX-RS resource with the following interface:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public interface PeopleResource extends PanacheEntityResource&lt;Person, Long&gt; {
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="panacherepositoryresource"><a class="anchor" href="#panacherepositoryresource"></a>PanacheRepositoryResource</h3>
<div class="paragraph">
<p>If your application has a simple entity (e.g. <code>Person</code>) and a repository (e.g. <code>PersonRepository</code>) that implements either <code>PanacheRepository</code> or <code>PanacheRepositoryBase</code> interface, you could instruct REST Data with Panache to generate its JAX-RS resource with the following interface:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public interface PeopleResource extends PanacheRepositoryResource&lt;PersonRepository, Person, Long&gt; {
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="the-generated-resource"><a class="anchor" href="#the-generated-resource"></a>The generated resource</h3>
<div class="paragraph">
<p>The generated resources will be functionally equivalent for both entities and repositories.
The only difference being the particular data access pattern in use.</p>
</div>
<div class="paragraph">
<p>If you have defined one of the <code>PeopleResource</code> interfaces mentioned above, REST Data with Panache will generate a JAX-RS resource similar to this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Path("/people") // Default path is a hyphenated lowercase resource name without a suffix of `resource` or `controller`.
public class PeopleResourceImpl implements PeopleResource { // The actual class name is going to be unique
    @GET
    @Produces("application/json")
    @Path("{id}")
    public Person get(@PathParam("id") Long id){
        // ...
    }

    @GET
    @Produces("application/json")
    public Response list(){
        // ...
    }

    @Transactional
    @POST
    @Consumes("application/json")
    @Produces("application/json")
    public Response add(Person entity) {
        // ..
    }

    @Transactional
    @PUT
    @Consumes("application/json")
    @Produces("application/json")
    @Path("{id}")
    public Response update(@PathParam("id") Long id, Person person) {
        // ..
    }

    @Transactional
    @DELETE
    @Path("{id}")
    public void delete(@PathParam("id") Long id) {
        // ..
    }
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="resource-customisation"><a class="anchor" href="#resource-customisation"></a>Resource customisation</h2>
<div class="sectionbody">
<div class="paragraph">
<p>REST Data with Panache provides a <code>@ResourceProperties</code> and <code>@MethodProperties</code> annotations that can be used to customize certain features of the resource.
It can be used in your resource interface:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ResourceProperties(hal = true, path = "my-people")
public interface PeopleResource extends PanacheEntityResource&lt;Person, Long&gt; {
    @MethodProperties(path = "all")
    Response list();

    @MethodProperties(exposed = false)
    void delete(Long id);
}</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="available-options"><a class="anchor" href="#available-options"></a>Available options</h3>
<div class="paragraph">
<p><code>@ResourceProperties</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>hal</code> - in addition to the standard <code>application/json</code> responses, generates additional methods that can return <code>application/hal+json</code> responses if requested via an <code>Accept</code> header.
Default is <code>false</code>.</p>
</li>
<li>
<p><code>path</code> - resource base path. Default path is a hyphenated lowercase resource name without a suffix of <code>resource</code> or <code>controller</code>.</p>
</li>
<li>
<p><code>paged</code> - whether collection responses should be paged or not.
First, last, previous and next page URIs are included in the response headers if they exist.
Request page index and size are taken from the <code>page</code> and <code>size</code> query parameters that default to <code>0</code> and <code>20</code> respectively.
Default is <code>true</code>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>@MethodProperties</code></p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>exposed</code> - does not expose a particular HTTP verb when set to <code>false</code>. Default is <code>true</code>.</p>
</li>
<li>
<p><code>path</code> - operation path (this is appended to the resource base path). Default is an empty string.</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="response-body-examples"><a class="anchor" href="#response-body-examples"></a>Response body examples</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As mentioned above REST Data with Panache supports the <code>application/json</code> and <code>application/hal+json</code> response content types.
Here are a couple of examples of how a response body would look like for the <code>get</code> and <code>list</code> operations assuming there are five <code>Person</code> records in a database.</p>
</div>
<div class="sect2">
<h3 id="get-people1"><a class="anchor" href="#get-people1"></a>GET /people/1</h3>
<div class="paragraph">
<p><code>Accept: application/json</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="json" class="language-json hljs">{
  "id": 1,
  "name": "John Johnson",
  "birth": "1988-01-10"
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>Accept: application/hal+json</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="json" class="language-json hljs">{
  "id": 1,
  "name": "John Johnson",
  "birth": "1988-01-10",
  "_links": {
    "self": {
      "href": "http://example.com/people/1"
    },
    "remove": {
      "href": "http://example.com/people/1"
    },
    "update": {
      "href": "http://example.com/people/1"
    },
    "add": {
      "href": "http://example.com/people"
    },
    "list": {
      "href": "http://example.com/people"
    }
  }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="get-peoplepage0size2"><a class="anchor" href="#get-peoplepage0size2"></a>GET /people?page=0&amp;size=2</h3>
<div class="paragraph">
<p><code>Accept: application/json</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="json" class="language-json hljs">[
  {
    "id": 1,
    "name": "John Johnson",
    "birth": "1988-01-10"
  },
  {
    "id": 2,
    "name": "Peter Peterson",
    "birth": "1986-11-20"
  }
]</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>Accept: application/hal+json</code></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="json" class="language-json hljs">{
  "_embedded": [
    {
      "id": 1,
      "name": "John Johnson",
      "birth": "1988-01-10",
      "_links": {
        "self": {
          "href": "http://example.com/people/1"
        },
        "remove": {
          "href": "http://example.com/people/1"
        },
        "update": {
          "href": "http://example.com/people/1"
        },
        "add": {
          "href": "http://example.com/people"
        },
        "list": {
          "href": "http://example.com/people"
        }
      }
    },
    {
      "id": 2,
      "name": "Peter Peterson",
      "birth": "1986-11-20",
      "_links": {
        "self": {
          "href": "http://example.com/people/2"
        },
        "remove": {
          "href": "http://example.com/people/2"
        },
        "update": {
          "href": "http://example.com/people/2"
        },
        "add": {
          "href": "http://example.com/people"
        },
        "list": {
          "href": "http://example.com/people"
        }
      }
    }
  ],
  "_links": {
    "add": {
      "href": "http://example.com/people"
    },
    "list": {
      "href": "http://example.com/people"
    },
    "first": {
      "href": "http://example.com/people?page=0&amp;size=2"
    },
    "last": {
      "href": "http://example.com/people?page=2&amp;size=2"
    },
    "next": {
      "href": "http://example.com/people?page=1&amp;size=2"
    }
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Both responses would also contain these headers:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Link: &lt; <a href="http://example.com/people?page=0&amp;size=2" class="bare">http://example.com/people?page=0&amp;size=2</a> &gt;; rel="first"</p>
</li>
<li>
<p>Link: &lt; <a href="http://example.com/people?page=2&amp;size=2" class="bare">http://example.com/people?page=2&amp;size=2</a> &gt;; rel="last"</p>
</li>
<li>
<p>Link: &lt; <a href="http://example.com/people?page=1&amp;size=2" class="bare">http://example.com/people?page=1&amp;size=2</a> &gt;; rel="next"</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>A <code>previous</code> link header (and hal link) would not be included, because the previous page does not exist.</p>
</div>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
